//
//  Primer_TypeErasure_DemoVC.swift
//  APSwift
//
//  Created by jianbo.pei on 2024/8/16.
//

import UIKit

class Primer_TypeErasure_DemoVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
//        test1()
        
        test21()
        test22()
    }

}

extension Primer_TypeErasure_DemoVC {
    protocol T1_Shape {
        associatedtype AreaType
        func area() -> AreaType
    }

    struct T1_Circle: T1_Shape {
        var radius: Double
        
        func area() -> Double {
            return .pi * radius * radius
        }
    }

    struct T1_Rectangle: T1_Shape {
        var width: Double
        var height: Double
        
        func area() -> Double {
            return width * height
        }
    }
    
    private func test1() {
        let shapes: [any T1_Shape] = [
            T1_Circle(radius: 5),
            T1_Rectangle(width: 10, height: 20)
        ]
        
        for shape in shapes {
            debugPrint("shape is \(shape)")
            debugPrint("shape type is \(type(of: shape))")
        }
    }
}

extension Primer_TypeErasure_DemoVC {
    protocol Plugin {
        func execute()
    }

    class PluginA: Plugin {
        func execute() {
            print("Plugin A executed")
        }
    }

    class PluginB: Plugin {
        func execute() {
            print("Plugin B executed")
        }
    }

    //---21
    private func test21() {
        let plugins: [any Plugin] = [PluginA(), PluginB()]

        for plugin in plugins {
            plugin.execute()
        }

        // 通过类型检查，你可以识别具体类型
        for plugin in plugins {
            print("21 \(type(of: plugin))")

            if let pluginA = plugin as? PluginA {
                print("Found PluginA")
            } else if let pluginB = plugin as? PluginB {
                print("Found PluginB")
            }
        }
    }
    
    //---31
    // 类型擦除实现
    class AnyPlugin: Plugin {
        private let _execute: () -> Void

        init<P: Plugin>(_ plugin: P) {
            _execute = plugin.execute
        }

        func execute() {
            _execute()
        }
    }
    
    private func test22() {
        let plugins: [AnyPlugin] = [AnyPlugin(PluginA()), AnyPlugin(PluginB())]

        for plugin in plugins {
            plugin.execute()
        }

        // 无法通过类型检查获取具体的实现类型
        for plugin in plugins {
            print("22 \(type(of: plugin))")
            
            if let pluginA = plugin as? PluginA {
                print("Found PluginA")
            } else if let pluginB = plugin as? PluginB {
                print("Found PluginB")
            }
        }
    }
}

